"""
    This module provides client request handling and responding
    Package: gameserver
    Project: PyBaldaJ
    Provides:
        class Handler
"""
#Logging support
import logging
#Multi threading support
import threading
#Implements Balda interface
from gameserver.game import balda
from gameserver.service import GameService

class Handler:

    def __init__(self, admin = None):
        self.WaitForEvent = threading.Event()
        self.logger = logging.getLogger('server.handler')
        self.game = balda.Game(admin = admin)
        self.eventQueue = list()
        self.playerEventId = dict()

    def ping(self):
        self.logger.info('Ping')
        return True

    def register_user(self, id):
        self.logger.debug('Registering user %i', id)
        try:
            self.game.add_player(id)
        except Exception, exc:
            self.logger.error('User %i: %s', id, exc.__class__.__name__)
            raise exc
        else:
            self.logger.info('User %i registered', id)
            self.playerEventId[id] = 0
            self.eventQueue.append(GameService.Event(type=GameService.EventType.USER_REGISTERED, id=id))
            if not self.WaitForEvent.is_set():
                self.WaitForEvent.set()
        return True

    def start_game(self, id):
        self.logger.debug('User %i trying to start the game', id)
        try:
            self.game.start(id)
        except Exception, exc:
            self.logger.error('User %i: %s', id, exc.__class__.__name__)
            raise exc
        else:
            self.logger.info('User %i started the game', id)
            self.logger.info('First word: %s', self.game.firstWord)
            self.eventQueue.append(GameService.Event(type=GameService.EventType.GAME_START, iword=self.game.firstWord))
            if not self.WaitForEvent.is_set():
                self.WaitForEvent.set()
            return self.game.firstWord

    def stop_game(self, id):
        self.logger.debug('User %i trying to stop the game', id)
        try:
            self.game.stop(id)
        except Exception, exc:
            self.logger.error('User %i: %s', id, exc.__class__.__name__)
            raise
        else:
            self.logger.info('User %i stopped the game', id)
            self.eventQueue.append(GameService.Event(type=GameService.EventType.GAME_START))
            if not self.WaitForEvent.is_set():
                self.WaitForEvent.set()
            return True

    def make_move(self, id, move):
        self.logger.debug('User %i is making attempt ot make move', id)
        self.logger.debug('Move :%s', move)
        try:
            self.game.make_move(id, move)
        except Exception, exc:
            self.logger.error('User %i: %s', id, exc.__class__.__name__)
            raise
        else:
            self.logger.info('User %i made move', id)
            self.eventQueue.append(GameService.Event(type=GameService.EventType.MOVE_MADE, move=move))
            if not self.WaitForEvent.is_set():
                self.WaitForEvent.set()
            return True

    def wait_for_event(self, id):
        self.logger.debug('User %i is waiting', id)
        if self.game.is_player(id):
            if len(self.eventQueue) == self.playerEventId[id]:
                self.WaitForEvent.clear()
                self.WaitForEvent.wait()
                self.logger.debug('User %i received an event', id)
                return self.eventQueue[len(self.eventQueue) - 1]
            else:
                eventId = self.playerEventId[id]
                self.playerEventId[id] += 1
                self.logger.debug('User %i received an event', id)
                return self.eventQueue[eventId]
        else:
            exc = NotRegistered()
            self.logger.error('User %i: %s', id, exc.__class__.__name__)
            raise exc
